import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Organization, OrganizationDocument } from './schemas/organization.schema';
import { CreateOrganizationDto } from './dto/create-organization.dto';
import { UpdateOrganizationDto } from './dto/update-organization.dto';
import { UsersService } from '../users/users.service';
import { RolesService } from '../roles/roles.service';

@Injectable()
export class OrganizationsService {
  constructor(
    @InjectModel(Organization.name) private organizationModel: Model<OrganizationDocument>,
    private usersService: UsersService,
    private rolesService: RolesService,
  ) {}

  async create(createOrganizationDto: CreateOrganizationDto): Promise<Organization> {
    // 检查同名机构是否存在
    const existingOrg = await this.organizationModel.findOne({ 
      name: createOrganizationDto.name 
    }).exec();
    
    if (existingOrg) {
      throw new BadRequestException('机构名称已存在');
    }
    
    // 如果指定了父机构，检查父机构是否存在
    if (createOrganizationDto.parentId) {
      const parentOrg = await this.organizationModel.findById(createOrganizationDto.parentId).exec();
      if (!parentOrg) {
        throw new BadRequestException('父机构不存在');
      }
    }
    
    const createdOrganization = new this.organizationModel(createOrganizationDto);
    return createdOrganization.save();
  }

  async findAll(parentId?: string): Promise<Organization[]> {
    if (parentId) {
      return this.organizationModel.find({ parentId }).sort({ sort: 1 }).exec();
    }
    return this.organizationModel.find().sort({ sort: 1 }).exec();
  }

  async findOne(id: string): Promise<Organization> {
    const organization = await this.organizationModel.findById(id).exec();
    
    if (!organization) {
      throw new NotFoundException(`机构 ID ${id} 不存在`);
    }
    
    return organization;
  }

  // 查找机构及其所有子机构
  async findOrganizationTree(parentId?: string): Promise<Organization[]> {
    // 获取所有机构
    const allOrgs = await this.organizationModel.find().sort({ sort: 1 }).exec();
    
    // 用于构建树的递归函数
    const buildTree = (parent?: string): Organization[] => {
      return allOrgs
        .filter(org => org.parentId?.toString() === (parent || null)?.toString())
        .map(org => ({
          ...org.toObject(),
          children: buildTree((org._id as any).toString())
        }));
    };
    
    return buildTree(parentId);
  }

  async update(id: string, updateOrganizationDto: UpdateOrganizationDto): Promise<Organization> {
    // 不允许将机构的父节点设置为其自身或其子节点
    if (updateOrganizationDto.parentId && updateOrganizationDto.parentId === id) {
      throw new BadRequestException('机构不能将自己设为父机构');
    }
    
    // 如果更新名称，检查是否存在同名机构
    if (updateOrganizationDto.name) {
      const existingOrg = await this.organizationModel.findOne({
        name: updateOrganizationDto.name,
        _id: { $ne: id }
      }).exec();
      
      if (existingOrg) {
        throw new BadRequestException('机构名称已存在');
      }
    }
    
    // 如果指定了父机构，检查父机构是否存在
    if (updateOrganizationDto.parentId) {
      const parentOrg = await this.organizationModel.findById(updateOrganizationDto.parentId).exec();
      if (!parentOrg) {
        throw new BadRequestException('父机构不存在');
      }
      
      // 检查是否会造成循环依赖
      const childOrgs = await this.findAllChildOrganizations(id);
      if (childOrgs.some(org => (org as any)._id.toString() === updateOrganizationDto.parentId)) {
        throw new BadRequestException('不能将子机构设为父机构');
      }
    }
    
    const updatedOrganization = await this.organizationModel.findByIdAndUpdate(
      id, 
      updateOrganizationDto, 
      { new: true }
    ).exec();
    
    if (!updatedOrganization) {
      throw new NotFoundException(`机构 ID ${id} 不存在`);
    }
    
    return updatedOrganization;
  }

  async remove(id: string): Promise<void> {
    const organization = await this.organizationModel.findById(id).exec();
    
    if (!organization) {
      throw new NotFoundException(`机构 ID ${id} 不存在`);
    }
    
    // 检查是否有子机构
    const hasChildren = await this.organizationModel.exists({ parentId: id }).exec();
    if (hasChildren) {
      throw new BadRequestException('该机构下有子机构，无法删除');
    }
    
    // 检查是否有关联用户
    const hasUsers = await this.usersService.hasUsersByOrgId(id);
    if (hasUsers) {
      throw new BadRequestException('该机构下有用户，无法删除');
    }
    
    // 检查是否有关联角色
    const hasRoles = await this.rolesService.hasRolesByOrgId(id);
    if (hasRoles) {
      throw new BadRequestException('该机构下有角色，无法删除');
    }
    
    await this.organizationModel.findByIdAndDelete(id).exec();
  }

  // 获取机构的所有子机构（递归）
  async findAllChildOrganizations(orgId: string): Promise<Organization[]> {
    const allOrgs = await this.organizationModel.find().exec();
    
    const findChildren = (parentId: string, result: Organization[] = []): Organization[] => {
      const children = allOrgs.filter(org => org.parentId?.toString() === parentId);
      
      children.forEach(child => {
        result.push(child);
        findChildren((child._id as any).toString(), result);
      });
      
      return result;
    };
    
    return findChildren(orgId);
  }
  
  // 批量删除机构
  async removeMany(ids: string[]): Promise<void> {
    // 对每个机构进行验证
    for (const id of ids) {
      const organization = await this.organizationModel.findById(id).exec();
      
      if (!organization) {
        throw new NotFoundException(`机构 ID ${id} 不存在`);
      }
      
      // 检查是否有子机构
      const hasChildren = await this.organizationModel.exists({ parentId: id }).exec();
      if (hasChildren) {
        throw new BadRequestException(`机构 ${organization.name} 下有子机构，无法删除`);
      }
      
      // 检查是否有关联用户
      const hasUsers = await this.usersService.hasUsersByOrgId(id);
      if (hasUsers) {
        throw new BadRequestException(`机构 ${organization.name} 下有用户，无法删除`);
      }
      
      // 检查是否有关联角色
      const hasRoles = await this.rolesService.hasRolesByOrgId(id);
      if (hasRoles) {
        throw new BadRequestException(`机构 ${organization.name} 下有角色，无法删除`);
      }
    }
    
    await this.organizationModel.deleteMany({ _id: { $in: ids } }).exec();
  }
} 